/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.shabby;

import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.pdfbox.cos.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.documentinterchange.markedcontent.PDPropertyList;

import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.pattern.PDAbstractPattern;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShading;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.util.Matrix;

import javax.imageio.ImageIO;

/**
 * 移除pdf水印
 *
 * @author Shabby WJT
 */
public final class wartermarkfilter
{
    static BufferedImage b1;
    static BufferedImage b2;

    static {
        try {
            //这里是两张水印的图片
            b1 = ImageIO.read(new FileInputStream("resource/watermark1.png"));
            b2 = ImageIO.read(new FileInputStream("resource/watermark2.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    TextWaterMarkFilter textWaterMarkFilter;

    /**
     * Default constructor.
     */
    private wartermarkfilter()
    {
        // example class should not be instantiated
    }

    /**
     * 移除所有水印的主函数.
     *
     * @param args The command line arguments.
     *
     * @throws IOException If there is an error parsing the document.
     */
    public static void main(String[] args) throws Exception
    {
        if (args.length != 2)
        {
            usage();
        }
        else
        {

            File test = new File(args[0]);
            new wartermarkfilter();
            wartermarkfilter worker = new wartermarkfilter();
            if(test.isFile()){
                File input_file = new File(args[0]);
                File output_file = new File(args[1]);
                worker.deal(input_file, output_file);
            }else{
                File input_dir = new File(args[0]);
                File output_dir = new File(args[1]);
                if(!output_dir.exists()){
                    output_dir.mkdirs();
                }else if(output_dir.isFile()){
                    output_dir.mkdirs();
                }
                if(!input_dir.exists() || !input_dir.isDirectory()){
                    throw new Exception("输入文件夹不存在");
                }

                for(File input_file:input_dir.listFiles()){
                    File output_file = new File(output_dir.getAbsolutePath()+"/__"+input_file.getName());
                    worker.deal(input_file, output_file);
                }
            }



        }

    }


    /**
     * 处理pdf中的资源,并返回过滤水印后的资源
     *
     * @param resources pdf资源
     *
     * @return PDResources 过滤后的pdf资源
     */
    private PDResources filterResources(PDResources resources) throws IOException
    {

        PDResources resources1=new PDResources();
        Iterable<COSName> names;

        names = resources.getPatternNames();
        for(COSName name:names){
            PDAbstractPattern pdAbstractPattern = resources.getPattern(name);
            resources1.put(name, pdAbstractPattern);
        }

        names = resources.getShadingNames();
        for(COSName name:names){
            PDShading pdShading = resources.getShading(name);
            resources1.put(name, pdShading);
        }

        names = resources.getExtGStateNames();
        for(COSName name:names){
            PDExtendedGraphicsState pdExtendedGraphicsState=resources.getExtGState(name);
            resources1.put(name, pdExtendedGraphicsState);
        }


        names = resources.getXObjectNames();
        for(COSName name:names){
            PDXObject pdxObject = resources.getXObject(name);

            //PDImageXObject
            //PDFormXObject
            if(pdxObject instanceof PDImageXObject){
                //图片排除，如果有图片水印，需要额外处理
                BufferedImage bufferedImage =((PDImageXObject) pdxObject).getImage();
                System.out.println(pdxObject);
                resources1.put(name, pdxObject);
            }else if (pdxObject instanceof PDFormXObject){
                resources1.put(name, pdxObject);
                System.out.println(pdxObject);
            }else{
                resources1.put(name, pdxObject);
            }
        }

        names = resources.getFontNames();
        for(COSName name:names){
            PDFont pdFont = resources.getFont(name);
            resources1.put(name, pdFont);
        }

        names = resources.getPropertiesNames();
        for(COSName name:names){
            PDPropertyList pdPropertyList = resources.getProperties(name);
            resources1.put(name, pdPropertyList);
        }

        names = resources.getColorSpaceNames();
        for(COSName name:names){
            PDColorSpace pdColorSpace = resources.getColorSpace(name);
            resources1.put(name, pdColorSpace);
        }

        return resources1;
    }



    private void filterResources(PDPage input, PDPage output) throws IOException
    {
        output.setResources(filterResources(input.getResources()));
    }



    /**
     * This will print the usage for this document.
     */
    private static void usage()
    {
        System.err.println(
                "Usage: java " + wartermarkfilter.class.getName() + " <input-dir> <output-dir>");
    }


    /**
     * 处理pdf中的资源,并返回过滤水印后的资源
     *
     * @param input pdf文件输入
     *
     * @param output pdf文件输出
     *
     */
    private void deal(File input, File output){

        try (PDDocument document = PDDocument.load(input))
        {
            PDDocument pdDocument = new PDDocument();

            if (document.isEncrypted())
            {
                System.err.println(
                        "Error: Encrypted documents are not supported for this example.");
            }

            int i = 0;

            for (PDPage inputPage : document.getPages())
            {

                textWaterMarkFilter = new TextWaterMarkFilter(inputPage,null,false);

                textWaterMarkFilter.initPage(inputPage);
                textWaterMarkFilter.pushResources(inputPage);

                textWaterMarkFilter.addFilter(new StringFilter() {
                    @Override
                    public String doFilter(String s, Matrix matrix) throws FilterReplaceException, FilterAbandonException {
                        if(s.equals("万方数据"))
                            throw new FilterReplaceException(s);
                        return s;
                    }
                });

                PDPage outputPage = new PDPage(inputPage.getMediaBox());
                filterResources(inputPage, outputPage);
                ArrayList<PDStream> contents = new ArrayList();
                for (Iterator<PDStream> it = inputPage.getContentStreams(); it.hasNext(); ) {
                    PDStream contentStream = it.next();
                    textWaterMarkFilter.processStreamOperators(contentStream);
                    contents.add(textWaterMarkFilter.getPDStream());
                }
                outputPage.setContents(contents);
                pdDocument.addPage(outputPage);

                System.out.println("____page_break_____");
            }

            pdDocument.save(output);
            pdDocument.close();
            document.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }



}